from utils import debug_info
import gc


class UDPServer:
	def __init__(self):
		import socket
		from config import Config
		from wifihandler import WifiHandler

		host = socket.getaddrinfo('0.0.0.0', Config.UDP_PORT)[0][-1]

		self._server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		self._server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self._server.bind(host)

		self._mac_address = WifiHandler.get_mac_address(WifiHandler.STA_MODE)

		debug_info("udp server bind on port %s" % Config.UDP_PORT)

	def start(self):
		from utime import sleep_ms

		while True:
			sleep_ms(300)

			data, address = self._server.recvfrom(1024)

			request = str(data, "utf-8").strip()

			if len(request) == 0:
				continue

			debug_info("received udp request: %s [%s:%s]" % (request, address[0], address[1]))

			self._respond_to_client(address, request)

			gc.collect()

	def _respond_to_client(self, address, request: str):
		from webservice.commands import Commands
		from product import Product

		respond_msg = ""
		need_feedback = False
		command = Commands.get_command(request)

		# received a query command
		if request.startswith(Commands.QUERY_PREFIX):
			if command == Commands.CMD_QUERY_ONLINE_STATUS:
				# device online, feedback to client with mac address
				need_feedback = True

				respond_msg = Commands.RESULT_QUERY_ONLINE_STATUS_SUCCESS
			else:
				# invalid command
				pass
		# received a control command
		elif request.startswith(Commands.QUERY_CONTROL_PREFIX):
			if type(Commands.get_mac_address(request)) is not bool:
				mac_address = Commands.get_mac_address(request)

				if mac_address != self._mac_address:
					# command not for me, ignore it
					return
			else:
				# invalid params
				debug_info("invalid params")

			if command in Product.CAPABILITY[Product.DEVICE_TYPE]:
				if Product.DEVICE_TYPE == "[ONE_SWITCH]":
					need_feedback = True

					if command == Commands.CMD_CONTROL_OS_POWER_ON:
						# power on
						respond_msg = Commands.RESULT_CONTROL_OS_POWER_ON_SUCCESS
					elif command == Commands.CMD_CONTROL_OS_POWER_OFF:
						# power off
						respond_msg = Commands.RESULT_CONTROL_OS_POWER_OFF_SUCCESS
					elif command == Commands.CMD_CONTROL_OS_TOGGLE_POWER:
						# toggle power
						respond_msg = Commands.RESULT_CONTROL_OS_TOGGLE_POWER_SUCCESS
			else:
				# invalid command
				debug_info("invalid command")
		else:
			# invalid command
			debug_info("invalid command")

		gc.collect()

		if need_feedback:
			self._server.sendto(respond_msg % self._mac_address, address)
